package controller

import (
	"EnjoyWorking/config"
	"EnjoyWorking/model"
	"EnjoyWorking/utils"
	"EnjoyWorking/utils/icasbin"
	"EnjoyWorking/utils/storage"
	"EnjoyWorking/web/middleware/jwt"
	"EnjoyWorking/web/service"
	"github.com/kataras/golog"
	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/hero"
	"strconv"
	"strings"
)

func NewAdminUserController(app *iris.Application, party iris.Party) {
	var (
		user       = party.Party("/user")
		controller = User{service: service.User{}}
	)

	user.Post("/create", hero.Handler(controller.create)).Name = "创建用户"
	user.Get("/getAll", hero.Handler(controller.getAll)).Name = "获取所有用户"

	user.Get("/getByDepartmentId", hero.Handler(controller.getByDepartmentId)).Name = "根据部门ID获取用户"

	user.Get("/get", hero.Handler(controller.get)).Name = "获取单个用户"
	user.Put("/update", hero.Handler(controller.update)).Name = "更新用户"
	user.Delete("/delete", hero.Handler(controller.delete)).Name = "删除用户"

	user.Post("/login", hero.Handler(controller.userLogin)).Name = "用户登录"
	user.Post("/logout", hero.Handler(controller.userLogout)).Name = "用户退出"
	user.Get("/profile", hero.Handler(controller.getProfile)).Name = "用户基础信息"

	list := app.GetRoutes()
	for _, v := range list {
		if v.Method == "OPTIONS" {
			continue
		}
		if strings.Index(v.Path, "/api/user") != -1 {
			v.Description = "用户管理接口"
		}
	}
}

type User struct {
	service service.User
}

func (c *User) userLogin(ctx iris.Context) {
	var (
		code       utils.Code
		err        error
		adminUser  = new(model.User)
		mAdminUser = new(model.User)
		ckPassword bool
		token      string
	)
	// TODO 同时登陆一个账号，将已登陆的用户挤下线
	if err = ctx.ReadJSON(&adminUser); err != nil {
		code = utils.CODE_SYS_PARSE_PARAMS_ERROR
		goto ERR
	}
	if err = utils.Validator().Struct(adminUser); err != nil {
		code = utils.CODE_SYS_PARSE_PARAMS_ERROR
		goto ERR
	}

	mAdminUser.UserName = adminUser.UserName
	mAdminUser.Enable = true
	if mAdminUser, err = c.service.FindOne(mAdminUser); err != nil {
		code = utils.CODE_USER_PHONE_FAILUR
		goto ERR
	}

	ckPassword = utils.CheckPWD(adminUser.PassWord, mAdminUser.PassWord)
	if !ckPassword {
		code = utils.CODE_USER_PASSWORD_FAILUR
		goto ERR
	}

	if token, err = jwt.G_JWT.GenerateToken(mAdminUser); err != nil {
		code = utils.CODE_TOKEN_CREATE_FAILUR
		goto ERR
	}
	if err = storage.G_Redis.SetToken(utils.REDIS_ADMIN_FORMAT, strconv.FormatUint(uint64(mAdminUser.ID), 10), token); err != nil {
		code = utils.CODE_TOKEN_CACHE_ERROR
		goto ERR
	}
	utils.Ok(ctx, utils.CODE_USER_LOGIN_OK, iris.Map{
		"token":  token,
		"expire": config.AppConfig().ExpireTime,
	})
	return
ERR:
	golog.Errorf("~~> admin后台用户[%s]登录失败。原因：%s，错误：%s", adminUser.UserName, code.String(), err)
	utils.InternalServerError(ctx, code, err)
}

func (c *User) get(ctx iris.Context) {
	var (
		code      utils.Code
		err       error
		adminUser *model.User
		uid       int64
	)
	if uid, err = ctx.URLParamInt64(utils.UID); err != nil {
		goto ERR
	}
	if adminUser, err = c.service.FindOne(&model.User{ID:uint(uid)}); err != nil {
		code = utils.CODE_SYS_FAILUR
		goto ERR
	}

	utils.Ok(ctx, utils.CODE_OK, &model.UserCopy{*adminUser})
	return
ERR:
	golog.Errorf("~~> 获取用户[%d]基础信息失败。原因：%s，错误：%s", uid, code.String(), err.Error())
	utils.InternalServerError(ctx, code, err)
	return
}

func (c *User) getByDepartmentId(ctx iris.Context) {
	var (
		code       utils.Code
		err        error
		uid        int64
		total      int64
		result     []*model.User
		resultCopy []*model.UserCopy
	)

	if uid, err = ctx.URLParamInt64("id"); err != nil {
		goto ERR
	}

	if total, result, err = c.service.FindByDepartmentId(uint(uid)); err != nil {
		goto ERR
	}

	for _, v := range result {
		resultCopy = append(resultCopy, &model.UserCopy{*v})
	}

	utils.PaginationTableData(ctx, total, resultCopy)
	return
ERR:
	golog.Errorf("失败。原因：%s，错误：%s", code.String(), err)
	utils.InternalServerError(ctx, code, err)
}

func (c *User) getAll(ctx iris.Context) {
	var (
		err    error
		code   utils.Code
		total  int64
		result []*model.User
		resultCopy []*model.UserCopy
	)

	if total, result, err = c.service.FindList(); err != nil {
		goto ERR
	}

	for _, v := range result {
		resultCopy = append(resultCopy, &model.UserCopy{*v})
	}

	utils.PaginationTableData(ctx, total, resultCopy)
	return
ERR:
	golog.Errorf("失败。原因：%s，错误：%s", code.String(), err)
	utils.InternalServerError(ctx, code, err)
}

func (c *User) update(context iris.Context) {

}

func (c *User) delete(context iris.Context) {

}

func (c *User) create(ctx iris.Context) {
	var (
		code utils.Code
		err  error
		vo = new(model.AcceptUserVO)
	)
	if err = ctx.ReadJSON(&vo); err != nil {
		code = utils.CODE_SYS_PARSE_PARAMS_ERROR
		goto ERR
	}

	if err = utils.Validator().Struct(vo); err != nil {
		code = utils.CODE_SYS_PARSE_PARAMS_ERROR
		goto ERR
	}

	vo.AdminUser.PassWord = utils.AESEncrypt([]byte(vo.AdminUser.PassWord))
	vo.AdminUser.Enable = true
	if err = c.service.Insert(vo); err != nil {
		code = utils.CODE_USER_PHONE_DUPLICATE
		goto ERR
	}
	icasbin.Casbin().LoadPolicy()
	utils.Ok_(ctx, utils.CODE_USER_REGISTE_OK)
	return
ERR:
	golog.Errorf("用户[%s]注册失败。原因：%s，错误：%s", vo.AdminUser.Phone, code, err)
	utils.InternalServerError(ctx, code, err)
}

func (c *User) userLogout(ctx iris.Context){
	var (
		err  error
		code utils.Code
		uid  int64
	)
	if uid, err = ctx.Values().GetInt64(utils.UID); err != nil {
		goto ERR
	}
	if _, err = storage.G_Redis.DelToken(utils.REDIS_ADMIN_FORMAT, strconv.FormatInt(uid, 10)); err != nil {
		code = utils.CODE_TOKEN_CACHE_ERROR
		goto ERR
	}
	utils.Ok_(ctx, utils.Code(200))
	return
ERR:
	golog.Errorf("~~> 用户[%d]退出失败。原因：%s，错误：%s", uid, code.String(), err)
	utils.InternalServerError(ctx, code, err)
	return
}

func (c *User) getProfile(ctx iris.Context) {
	var (
		code      utils.Code
		err       error
		adminUser *model.User
		uid       uint
	)
	if uid, err = ctx.Values().GetUint(utils.UID); err != nil {
		goto ERR
	}
	if adminUser, err = c.service.FindOne(&model.User{ID:uid}); err != nil {
		code = utils.CODE_SYS_FAILUR
		goto ERR
	}

	adminUser.PassWord = ""
	adminUser.Online = true
	utils.Ok(ctx, utils.CODE_USER_LOGIN_OK, &model.UserCopy{*adminUser})
	return
ERR:
	golog.Errorf("~~> 获取用户[%d]基础信息失败。原因：%s， 错误：%s", uid, code.String(), err.Error())
	utils.InternalServerError(ctx, code, err)
	return
}

